package org.zjt.akka;

import akka.actor.*;
import lombok.extern.slf4j.Slf4j;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.concurrent.TimeUnit;

/**
 * Description:   多个actor之间的相互发送事件。
 *              链式发送。和dirupter不一样。
 *
 * @author juntao.zhang
 * Date: 2018-06-26 下午9:21
 * @see
 */
@Slf4j
public class GreeterTest {

    /**
     *  messages
     */
    private static class Greet {

        public final ActorRef target;

        public Greet(ActorRef actor) {
            target = actor;
        }
    }

    private static Object AskName = new Object();

    private static class TellName {
        public final String name;

        public TellName(String name) {
            this.name = name;
        }
    }


    /**
     *  actor implementation
     */
    private static class Greeter extends AbstractActor {

        private final String myName;
        private final String greeting;

        Greeter(String name, String greeting) {
            myName = name;
            this.greeting = greeting;
        }

        /**
         * 调用Greeter的构造函数生成实例，创建actor实例。
         * @param name
         * @param greeting
         * @return
         */
        public static Props props(String name, String greeting) {
            return Props.create(Greeter.class, name, greeting);
        }


        /**
         * 接受消息处理
         * @param message
         * @throws Exception
         */
        public void onReceive(Object message) throws Exception {
            if (message instanceof Greet) {
                ((Greet)message).target.tell(AskName, self());
            } else if (message == AskName) {
                /** 得到发送器，并发送信息，带上当前发送者信息 **/
                sender().tell(new TellName(myName), self());
            } else if (message instanceof TellName) {
                log.info(greeting + ", " + ((TellName)message).name);
            }
        }

        /**
         * 创建消息接受处理实例
         * @return
         */
        @Override
        public Receive createReceive() {
            return receiveBuilder().match(Object.class,this::onReceive).build();
        }
    }



    ActorSystem system ;

    @Before
    public void startup() {
        system = ActorSystem.create("testSystem");
    }

    /**
     * 相互传话逻辑
     */
    @Test
    public void method1() {
        ActorRef bob = system.actorOf(Greeter.props("Bob", "Howya doing"));
        ActorRef alice = system.actorOf(Greeter.props("Alice", "Happy to meet you"));

        // bob  -> alice，发送事件给this。  参数二：发件人，如果没有则可以是noSender
        bob.tell(new Greet(alice), ActorRef.noSender());

        // alice -> bob
        alice.tell(new Greet(bob), ActorRef.noSender());
    }



    @After
    public void shutdown() throws InterruptedException {
        TimeUnit.SECONDS.sleep(20);
        system.terminate();
    }

}
